package com.sjb.cp.service.impl;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.sjb.cp.exception.BusinessException;
import com.sjb.cp.exception.ErrorCode;
import com.sjb.cp.exception.ThrowUtils;
import com.sjb.cp.model.po.Picture;
import com.sjb.cp.model.po.Space;
import com.sjb.cp.model.po.User;
import com.sjb.cp.model.request.analyze.*;
import com.sjb.cp.model.vo.*;
import com.sjb.cp.service.PictureService;
import com.sjb.cp.service.SpaceAnalyzeService;
import com.sjb.cp.service.SpaceService;
import com.sjb.cp.service.UserService;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Author:sjb
 * @CreateTime:2025-02-12
 * @Description: 空间分析服务实现类
 * @Version：1.0
 */
@Component
public class SpaceAnalyzeServiceImpl implements SpaceAnalyzeService {

    @Resource
    private SpaceService spaceService;

    @Resource
    private UserService userService;

    @Resource
    private PictureService pictureService;

    @Override
    public void checkSpaceAnalyzeAuth(SpaceAnalyzeRequest spaceAnalyzeRequest, User loginUser) {
        ThrowUtils.throwIf(spaceAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);

        if (spaceAnalyzeRequest.isQueryAll() || spaceAnalyzeRequest.isQueryPublic()){
            // 仅管理员可用的分析全部空间
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR,"无公共空间权限");
        }else {
            // 私有空间权限校验
            String spaceId = spaceAnalyzeRequest.getSpaceId();
            Space space = spaceService.getById(spaceId);
            ThrowUtils.throwIf(space == null,ErrorCode.NOT_FOUND_ERROR,"空间不存在");
            if (!loginUser.getId().equals(space.getUserId())){
                throw new BusinessException(ErrorCode.NO_AUTH_ERROR,"无此空间权限");
            }
        }
    }

    @Override
    public SpaceUsageAnalyzeVo getSpaceUsageAnalyze(SpaceAnalyzeRequest spaceAnalyzeRequest,
                                                    User loginUser) {
        ThrowUtils.throwIf(spaceAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);

        if (spaceAnalyzeRequest.isQueryAll() || spaceAnalyzeRequest.isQueryPublic()){
            // 仅管理员可使用的查询全部
            boolean admin = userService.isAdmin(loginUser);
            if (!admin){
                throw new BusinessException(ErrorCode.NO_AUTH_ERROR,"非管理员,无权限操作");
            }

            QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
            queryWrapper.select("picSize");
            if (!spaceAnalyzeRequest.isQueryAll()){
                queryWrapper.isNull("spaceId");
            }

            List<Object> pictureObjLists = pictureService.getBaseMapper().selectObjs(queryWrapper);
            long usedSize = pictureObjLists.stream().mapToLong(result -> result instanceof Long ? (Long) result : 0).sum();
            SpaceUsageAnalyzeVo spaceUsageAnalyzeVo = new SpaceUsageAnalyzeVo();
            long usedCount = pictureObjLists.size();
            spaceUsageAnalyzeVo.setUsedSize(usedSize);
            spaceUsageAnalyzeVo.setUsedCount(usedCount);

            // 公共图库无上限，无比例
            spaceUsageAnalyzeVo.setSizeUsageRatio(null);
            spaceUsageAnalyzeVo.setMaxCount(null);
            spaceUsageAnalyzeVo.setMaxSize(null);
            spaceUsageAnalyzeVo.setCountUsageRatio(null);
            return spaceUsageAnalyzeVo;

        }else {
            // 查询指定空间
            String spaceId = spaceAnalyzeRequest.getSpaceId();
            Space space = spaceService.getById(spaceId);
            ThrowUtils.throwIf(space == null,ErrorCode.NOT_FOUND_ERROR,"空间不存在");
            if (!loginUser.getId().equals(space.getUserId())){
                throw new BusinessException(ErrorCode.NO_AUTH_ERROR,"无空间权限");
            }
            SpaceUsageAnalyzeVo spaceUsageAnalyzeVo = new SpaceUsageAnalyzeVo();
            spaceUsageAnalyzeVo.setMaxSize(space.getMaxSize());
            spaceUsageAnalyzeVo.setMaxCount(space.getMaxCount());
            spaceUsageAnalyzeVo.setUsedSize(space.getTotalSize());
            spaceUsageAnalyzeVo.setUsedCount(space.getTotalCount());
            double sizeUsageRatio = NumberUtil.round(space.getTotalSize() * 100.0 / space.getMaxSize(),2).doubleValue();
            spaceUsageAnalyzeVo.setSizeUsageRatio(sizeUsageRatio);
            double countUsageRation = NumberUtil.round(space.getTotalCount() * 100.0 / space.getMaxCount(),2).doubleValue();
            spaceUsageAnalyzeVo.setCountUsageRatio(countUsageRation);
            return spaceUsageAnalyzeVo;
        }

    }

    @Override
    public List<SpaceCategoryAnalyzeVo> getSpaceCategoryAnalyzeList(SpaceCategoryAnalyzeRequest spaceCategoryAnalyzeRequest,
                                                                    User loginUser) {
        ThrowUtils.throwIf(spaceCategoryAnalyzeRequest == null,ErrorCode.PARAMS_ERROR);

        // todo 权限校验

        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        // 根据分析范围补充查询条件
        fillSpaceAnalyzeWrapper(spaceCategoryAnalyzeRequest, queryWrapper);
        // 构造查询条件
        queryWrapper.select("category As category","count(*) as count","SUM(size) as totalSize")
                .groupBy("category");

        return pictureService.getBaseMapper().selectMaps(queryWrapper)
                .stream().map(picture -> {
                    String category = picture.get("category") != null ? picture.get("category").toString() : "未分类";
                    Long count = ((Number) picture.get("count")).longValue();
                    Long totalSize = ((Number) picture.get("totalSize")).longValue();
                    return new SpaceCategoryAnalyzeVo(category, count, totalSize);
                }).collect(Collectors.toList());

    }

    @Override
    public List<SpaceTagAnalyzeVo> getSpaceTagAnalyzeList(SpaceTagAnalyzeRequest spaceTagAnalyzeRequest,
                                                               User loginUser) {
        ThrowUtils.throwIf(spaceTagAnalyzeRequest == null,ErrorCode.PARAMS_ERROR);
        // todo 权限校验

        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        fillSpaceAnalyzeWrapper(spaceTagAnalyzeRequest, queryWrapper);
        queryWrapper.select("tags");

        // 查询所有符合条件的标签
        List<String> tagList = pictureService.getBaseMapper().selectObjs(queryWrapper)
                .stream().filter(ObjectUtil::isNotNull)
                .map(Object::toString).collect(Collectors.toList());

        // 合并所有标签并统计使用次数
        Map<String, Long> tagsCount = tagList.stream().flatMap(tagsJson -> JSONUtil.toList(tagsJson, String.class).stream())
                .collect(Collectors.groupingBy(tag -> tag, Collectors.counting()));

        // 转为响应对象，按照响应次数降序排列
        return tagsCount.entrySet().stream()
                .sorted((e1, e2) -> Long.compare(e2.getValue(), e1.getValue()))
                .map(response -> new SpaceTagAnalyzeVo(response.getKey(), response.getValue()))
                .collect(Collectors.toList());
    }

    @Override
    public List<SpaceSizeAnalyzeVo> getSpaceSizeAnalyze(SpaceSizeAnalyzeRequest spaceSizeAnalyzeRequest,
                                                        User loginUser) {
        ThrowUtils.throwIf(spaceSizeAnalyzeRequest == null,ErrorCode.PARAMS_ERROR);

        // todo 权限校验

        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        fillSpaceAnalyzeWrapper(spaceSizeAnalyzeRequest,queryWrapper);

        queryWrapper.select("picSize");

        List<Long> sizeList = pictureService.getBaseMapper().selectObjs(queryWrapper)
                .stream().map(size -> ((Number) size).longValue())
                .collect(Collectors.toList());

        // 分段
        Map<String,Long> sizeRanges = new LinkedHashMap<>();
        sizeRanges.put("<100KB",sizeList.stream().filter(size -> size < 100 * 1024).count());
        sizeRanges.put("100KB-500KB",sizeList.stream().filter(size -> size >= 100 * 1024 && size <= 500 * 1024).count());
        sizeRanges.put("500KB-1MB",sizeList.stream().filter(size -> size > 500 * 1024 && size <= 1 * 1024 * 1024).count());
        sizeRanges.put(">1MB",sizeList.stream().filter(size -> size > 1 * 1024 * 1024).count());

        // 转换为响应对象
        return sizeRanges.entrySet().stream()
                .map(entry -> new SpaceSizeAnalyzeVo(entry.getKey(), entry.getValue())).collect(Collectors.toList());
    }

    @Override
    public List<SpaceUserAnalyzeVo> getSpaceUserAnalyze(SpaceUsageAnalyzeRequest spaceUsageAnalyzeRequest,
                                                        User loginUser) {
        ThrowUtils.throwIf(spaceUsageAnalyzeRequest == null,ErrorCode.PARAMS_ERROR);

        // todo权限校验
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        Long userId = spaceUsageAnalyzeRequest.getUserId();
        queryWrapper.eq(ObjectUtil.isNotNull(userId),"userId",userId);
        fillSpaceAnalyzeWrapper(spaceUsageAnalyzeRequest, queryWrapper);

        String timeDimension = spaceUsageAnalyzeRequest.getTimeDimension();
        switch (timeDimension) {
            case "day":
                queryWrapper.select("DATE_FORMAT(create_time,'%Y-%m-%d') as period","count(*) as count");
                break;
            case "week":
                queryWrapper.select("YEARWEEK(create_time) as period","count(*) as count");
                break;
            case "month":
                queryWrapper.select("DATE_FORMAT(create_time,'%Y-%m') as period","count(*) as count");
                break;
            default:
                throw new BusinessException(ErrorCode.PARAMS_ERROR,"不支持的时间排序");
        }

        // 分组和排序
        queryWrapper.groupBy("period").orderByAsc("period");

        List<Map<String, Object>> userAnalyzeMaps = pictureService.getBaseMapper().selectMaps(queryWrapper);

        return userAnalyzeMaps.stream().map(
                result -> {
                    String period = result.get("period").toString();
                    long count = ((Number) result.get("count")).longValue();
                    return new SpaceUserAnalyzeVo(period, count);
                }).collect(Collectors.toList());
    }

    @Override
    public List<Space> getTopSpace(SpaceRankAnalyzeRequest spaceRankAnalyzeRequest,
                                   User loginUser) {
        ThrowUtils.throwIf(spaceRankAnalyzeRequest == null,ErrorCode.PARAMS_ERROR);
        // todo 权限校验
        QueryWrapper<Space> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("id","spaceName","userId","totalSize")
                .orderByDesc("totalSize")
                .last("limit " + spaceRankAnalyzeRequest.getTopN());

        return spaceService.list(queryWrapper);
    }


    /**
     * 填充查询指定范围的条件
     * @param spaceAnalyzeRequest
     * @param pictureWrapper
     */
    public void fillSpaceAnalyzeWrapper(SpaceAnalyzeRequest spaceAnalyzeRequest,
                                        QueryWrapper<Picture> pictureWrapper) {
        if (spaceAnalyzeRequest.isQueryAll()){
            return;
        }
        if (spaceAnalyzeRequest.isQueryPublic()){
            pictureWrapper.isNull("spaceId");
            return;
        }
        String spaceId = spaceAnalyzeRequest.getSpaceId();
        if (spaceId != null){
            pictureWrapper.eq("spaceId", spaceId);
        }
        throw new BusinessException(ErrorCode.PARAMS_ERROR,"未指定查询范围");
    }
}
